package edu.cs.usask.ca.silver.plugin.rcp.dialogs.create;

import java.io.File;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import edu.cs.usask.ca.silver.businesslogic.ids.ModelVersionID;

public class CreateScenarioCollectionDialog extends Dialog {

	private Text scenarioCollectionNameText;
	private Text scenarioCollectionCreatorText;
	private Text scenarioCollectionDescriptionText;
	private List visualListAssociatedFiles;
	private List visualListTrajectoryFiles;

	private String scenarioCollectionName;
	private String scenarioCollectionCreator;
	private String scenarioCollectionDescription;
	// having this array simplifies the use of the same code for handling these
	// cases
	private Boolean[] arrayAreFilesRequested = { true, false }; // first for
																// arbitrary
																// associated
																// files, second
																// for
																// trajectory
																// files.
	
	private final ModelVersionID modelVersionId;

	// to allow the user flexibility in adding files over several steps, these
	// final two variables aren't set until the dialog box is closing
	private String[] arrayStrAssociatedFiles;
	private String[] arrayStrTrajectoryFilesForReconstructingScenarios = null;

	public CreateScenarioCollectionDialog(Shell parentShell,
			ModelVersionID selectedmodelVersionId) {
		super(parentShell);
		modelVersionId = selectedmodelVersionId;
	}

	@Override
	protected void configureShell(Shell newShell) {
		super.configureShell(newShell);
		newShell.setText("Create New Scenario Collection");
	}

	@Override
	protected Control createDialogArea(Composite parent) {

		final Composite composite = new Composite(parent, SWT.BORDER);
		composite.setLayout(new GridLayout(3, false));

		// set up basics of grid
		Label scenarioCollectionNameLabel = new Label(composite, SWT.NONE);
		scenarioCollectionNameLabel.setText("&Collection Name");

		scenarioCollectionNameText = new Text(composite, SWT.BORDER);
		GridData gridData = new GridData();
		gridData.horizontalAlignment = SWT.FILL;
		gridData.grabExcessHorizontalSpace = true;
		gridData.horizontalSpan = 2;
		scenarioCollectionNameText.setLayoutData(gridData);

		Label scenarioCollectionCreatorLabel = new Label(composite, SWT.NONE);
		scenarioCollectionCreatorLabel.setText("&Collection Creator:");
		gridData = new GridData();
		gridData.verticalAlignment = SWT.TOP;
		scenarioCollectionCreatorLabel.setLayoutData(gridData);

		scenarioCollectionCreatorText = new Text(composite, SWT.BORDER);
		gridData = new GridData();
		gridData.horizontalAlignment = SWT.FILL;
		gridData.grabExcessHorizontalSpace = true;
		gridData.horizontalSpan = 2;
		scenarioCollectionCreatorText.setLayoutData(gridData);
		scenarioCollectionCreatorText.setText(System.getProperty("user.name"));

		Label scenarioCollectionDescriptionLabel = new Label(composite,
				SWT.NONE);
		scenarioCollectionDescriptionLabel.setText("&Collection Description:");
		gridData = new GridData();
		gridData.verticalAlignment = SWT.TOP;
		scenarioCollectionDescriptionLabel.setLayoutData(gridData);

		scenarioCollectionDescriptionText = new Text(composite, SWT.BORDER
				| SWT.WRAP | SWT.MULTI);
		gridData = new GridData();
		gridData.horizontalAlignment = SWT.FILL;
		gridData.grabExcessHorizontalSpace = true;
		gridData.minimumHeight = scenarioCollectionDescriptionText
				.getLineHeight() * 5;
		gridData.grabExcessVerticalSpace = true;
		gridData.horizontalSpan = 2;
		scenarioCollectionDescriptionText.setLayoutData(gridData);

		// Associated Files
		Group associateFilesGroup = new Group(composite, SWT.NONE);
		visualListAssociatedFiles = CreateFilesCategoryButtonsAndDisplay(
				gridData, "Associated Files", 0, associateFilesGroup, "*.*",
				SWT.OPEN | SWT.MULTI);

		// Trajectory Files
		Group trajectoryFilesGroup = new Group(composite, SWT.NONE);

		// TODO: Make this more generc so we don't hard-code the file filter
		final String strTrajectoryFileFilter = "*.vdf";
		visualListTrajectoryFiles = CreateFilesCategoryButtonsAndDisplay(
				gridData, "Trajectory Files for Reconstructing Scenarios", 1,
				trajectoryFilesGroup, strTrajectoryFileFilter, SWT.OPEN
						| SWT.MULTI);

		/*
		 * try {
		 * EstablishAndConfigureLoadSimulationsButton(ModelVersionLocalClient
		 * .getService().getType(m_modelVersionId), trajectoryFilesGroup,
		 * visualListTrajectoryFiles); } catch (Exception e) {
		 * LoggerReportScheduler.scheduleErrorLogging(logger,""Error in attempting to get the simulation type for scenario " + "m_modelVersionId", e); }
		 */

		return composite;
	} /* end of createDialogArea */

	List CreateFilesCategoryButtonsAndDisplay(GridData gridData,
			final String strContents, final int iFilesType, final Group group,
			final String strFileFilter, final int dialogFlags) {
		// configure buttons, etc.
		group.setText(strContents);
		gridData = new GridData();
		gridData.verticalIndent = 10;
		gridData.horizontalSpan = 3;
		gridData.horizontalAlignment = SWT.FILL;
		group.setLayoutData(gridData);
		group.setLayout(new GridLayout(3, true));

		final Button associateFileCheckBox = new Button(group, SWT.CHECK);
		associateFileCheckBox.setText("&Create with " + strContents);
		associateFileCheckBox.setSelection(false);
		gridData = new GridData();
		gridData.horizontalSpan = 3;
		associateFileCheckBox.setLayoutData(gridData);

		final Label associateFileLabel = new Label(group, SWT.END);
		associateFileLabel.setText("&List of " + strContents);

		// Multiple-selection list for associated files
		final List visualListOfFiles = new List(group, SWT.MULTI | SWT.BORDER
				| SWT.V_SCROLL | SWT.H_SCROLL);
		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
		gridData.horizontalSpan = 3;
		visualListOfFiles.setLayoutData(gridData);

		final Label listCountLabel = new Label(group, SWT.LEFT);
		listCountLabel.setText(String.valueOf(visualListOfFiles.getItemCount())
				+ " files added.");

		final Button removeFile = new Button(group, SWT.PUSH | SWT.RIGHT);
		removeFile.setAlignment(SWT.CENTER);
		removeFile.setText("Remove");
		removeFile.setToolTipText("Remove the last added file from the list.");
		gridData = new GridData();
		gridData.horizontalAlignment = SWT.END;

		removeFile.setLayoutData(gridData);

		removeFile.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (visualListOfFiles.getItemCount() == 0) {
					return;
				}
				visualListOfFiles.remove(visualListOfFiles.getItemCount() - 1);
			}
		});

		final Button loadFile = new Button(group, SWT.PUSH | SWT.RIGHT);
		loadFile.setAlignment(SWT.CENTER);
		loadFile.setText("Add..");
		loadFile.setToolTipText("Add any types of files from system, the "
				+ "absolute file path will be added to the list");

		loadFile.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				FileDialog fileDialog = new FileDialog(group.getShell(),
						dialogFlags);
				fileDialog.setFilterExtensions(new String[] { strFileFilter });
				fileDialog.setFilterNames(new String[] { strContents + "("
						+ strFileFilter + ")" });
				fileDialog.setText("Load " + strContents);

				if (fileDialog.open() != null) {
					// if the user did not cancel the dialogue box, get the list
					// of trajectory files
					// remember these as trajectory files for extraction of
					// scenario information
					String[] arrayStrTrajectoryFiles = AppendPathToFileNames(
							fileDialog.getFilterPath(),
							fileDialog.getFileNames());
					// disabled: also treat these files as files associated with
					// this scenario collection (if do this, need to also
					// refresh the associated file list)
					AddFilesToVisualList(arrayStrTrajectoryFiles,
							visualListOfFiles);

					listCountLabel.setText(String.valueOf(visualListOfFiles
							.getItemCount()) + " files loaded.");
				}

			}
		});

		/*
		 * Use check box to control whether user wants to add associate file
		 * with Project
		 */
		associateFileCheckBox.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				loadFile.setEnabled(associateFileCheckBox.getSelection());
				removeFile.setEnabled(associateFileCheckBox.getSelection());
				visualListOfFiles.setEnabled(associateFileCheckBox
						.getSelection());
				associateFileLabel.setEnabled(associateFileCheckBox
						.getSelection());
				arrayAreFilesRequested[iFilesType] = associateFileCheckBox
						.getSelection();
				listCountLabel.setEnabled(associateFileCheckBox.getSelection());
			}
		});

		loadFile.setEnabled(associateFileCheckBox.getSelection());
		removeFile.setEnabled(associateFileCheckBox.getSelection());
		visualListOfFiles.setEnabled(associateFileCheckBox
				.getSelection());
		associateFileLabel.setEnabled(associateFileCheckBox
				.getSelection());
		arrayAreFilesRequested[iFilesType] = associateFileCheckBox
				.getSelection();
		listCountLabel.setEnabled(associateFileCheckBox.getSelection());
		return visualListOfFiles;
	}

	/**
	 * the data supplied to stored into local variable to be extracted using the
	 * get method by the CreateModelVersionAction class. This method checks to
	 * make sure that all the fields are filled out
	 * 
	 */
	@Override
	protected void okPressed() {

		scenarioCollectionName = scenarioCollectionNameText.getText();
		scenarioCollectionCreator = scenarioCollectionCreatorText.getText();
		scenarioCollectionDescription = scenarioCollectionDescriptionText
				.getText();

		if (scenarioCollectionName.isEmpty()) {
			MessageDialog.openError(getShell(),
					"Invalid Scenario Collection Name",
					"Please fill in the Scenario Collection name.");
			return;
		}

		if (scenarioCollectionCreator.isEmpty()) {
			MessageDialog.openError(getShell(),
					"Invalid Scenario Collection Creator",
					"Please fill in the creator for the Scenario Collection.");
			return;
		}

		if (scenarioCollectionDescription.isEmpty()) {
			if (!MessageDialog
					.openConfirm(getShell(),
							"Empty Scenario Collection Description",
							"Is it OK to leave description empty for now?")) {
				return;
			}
		}

		if (getAreAssociateFilesRequested()) {
			File temp;
			if (visualListAssociatedFiles.getItemCount() == 0) {
				if (MessageDialog
						.openConfirm(
								this.getParentShell(),
								"Non Associate Files listed",
								"You checked to add associate files but did not add any to the list. OK to proceed?")) {
					setAreAssociateFilesRequested(false);
				} else {
					return;
				}
			} else {
				// check if files can be loaded
				for (int index = 0; index < visualListAssociatedFiles
						.getItemCount(); index++) {
					temp = new File(visualListAssociatedFiles.getItem(index));
					if (!temp.canRead()) {
						MessageDialog.openError(
								getShell(),
								"File Open Error",
								"Unable to open Associate File at "
										+ visualListAssociatedFiles
												.getItem(index));
						return;
					}
				}
			}

			arrayStrAssociatedFiles = visualListAssociatedFiles.getItems();
		}

		arrayStrTrajectoryFilesForReconstructingScenarios = visualListTrajectoryFiles
				.getItems();

		super.okPressed();
	} /* end of okPressed */

	/*
	 * private void EstablishAndConfigureLoadSimulationsButton(final String
	 * strSimulationType, final Composite compositeSurroundingContext, final
	 * List visualListTrajectoryFiles) { Button loadSimulationButton =
	 * EstablishLoadSimulationsButton(strSimulationType,
	 * compositeSurroundingContext);
	 * logger.info("At EstablishAndConfigureLoadSimulationsButton #1");
	 * 
	 * loadSimulationButton.addSelectionListener(new SelectionAdapter() {
	 * 
	 * @Override public void widgetSelected(SelectionEvent e) {
	 * logger.info("At EstablishAndConfigureLoadSimulationsButton #2");
	 * FileDialog fileDialog = new
	 * FileDialog(compositeSurroundingContext.getShell(), SWT.OPEN | SWT.MULTI);
	 * fileDialog.setFilterExtensions(new String[] { "*.vdf" });
	 * fileDialog.setFilterNames(new String[] { "Trajectory files (*.vdf)" });
	 * fileDialog.setText("Reconstruct Parameters from Trajectory File:");
	 * 
	 * try { // Don't actually add in the file to the database yet -- just add
	 * to the associated // files.
	 * 
	 * // we remember any trajectory files for when we return from this dialog
	 * box; they will then be processed
	 * 
	 * // if the user canceled the dialog box, don't change the list of
	 * trajectory files. if (fileDialog.open() != null) { // if the user did not
	 * cancel the dialogue box, get the list of trajectory files // remember
	 * these as trajectory files for extraction of scenario information String
	 * []arrayStrTrajectoryFiles =
	 * AppendPathToFileNames(fileDialog.getFilterPath(),
	 * fileDialog.getFileNames()); // disabled: also treat these files as files
	 * associated with this scenario collection (if do this, need to also
	 * refresh the associated file list)
	 * AddFilesToVisualList(arrayStrTrajectoryFiles, visualListTrajectoryFiles);
	 * } } catch (Exception e1) { LoggerReportScheduler.scheduleErrorLogging(logger,e1); }
	 * }
	 * 
	 * });
	 * 
	 * 
	 * }
	 */
	// return an array in which given path is appended to all of the file names
	public String[] AppendPathToFileNames(String strPath,
			String[] arrayFileNames) {
		String[] arrayAugmentedFileNames = new String[arrayFileNames.length];
		String strPathPlusSeparator = strPath + "/"; // this separator appears
														// to work with both
														// windows an other
														// platforms

		for (int i = 0; i < arrayFileNames.length; i++)
			arrayAugmentedFileNames[i] = strPathPlusSeparator
					+ arrayFileNames[i];

		return arrayAugmentedFileNames;
	}

	/*
	 * public static Button EstablishLoadSimulationsButton(final String
	 * strSimulationType, final Composite compositeSurroundingContext) { Button
	 * loadSimulationButton = new Button(compositeSurroundingContext,
	 * SWT.RIGHT); // only enable the button for simulation types that support
	 * trajectory files
	 * 
	 * // TODO: ***For easier modification, we should really abstract out this
	 * test so that it occurs in a single
	 * loadSimulationButton.setEnabled(strSimulationType
	 * .equalsIgnoreCase("VENSIM"));
	 * 
	 * loadSimulationButton.setText("Load " + strSimulationType +
	 * " Trajectory files (storing them until 'OK' is pressed).");
	 * 
	 * //
	 * runSimLabel.setBackground(top.getDisplay().getSystemColor(SWT.COLOR_RED
	 * )); // arrange for how the button is to be laid out
	 * loadSimulationButton.setLayoutData(new GridData(GridData.END,
	 * GridData.CENTER, false, false)); // set the tooltip
	 * loadSimulationButton.setToolTipText(
	 * "Create scenarios for this scenario collection from one or more trajectory files, drawing parameter values for each such scenario from the corresponding trajectory file."
	 * );
	 * 
	 * // editName.addSelectionListener(new //
	 * RenameButtonSelectionAdapter(parent, getModelObjectID(), //
	 * getModelObjectName())),
	 * 
	 * return loadSimulationButton; }
	 */

	private void AddFilesToVisualList(String[] arrayFiles,
			List associatedFileList) {
		for (String strFile : arrayFiles)
			associatedFileList.add(strFile);
	}

	/**
	 * a method to get the new scenario collection name
	 * 
	 * @return String containing the collection name
	 */
	public String getscenarioCollectionName() {
		return scenarioCollectionName;
	}

	/**
	 * a method to get the new scenario collection creator
	 * 
	 * @return String containing the collection creator
	 */
	public String getscenarioCollectionCreator() {
		return scenarioCollectionCreator;
	}

	/**
	 * a method to get the new scenario collection description
	 * 
	 * @return String containing the collection description
	 */
	public String getscenarioCollectionDescription() {
		return scenarioCollectionDescription;
	}

	/**
	 * this method returns the selection of check box for associate file group.
	 * Different ScenarioCollection creation method is initiated based on the
	 * user choice.
	 * 
	 * @return Boolean - whether check box is checked
	 */
	public Boolean getAreAssociateFilesRequested() {
		return arrayAreFilesRequested[0];
	}

	/**
	 * this method returns the selection of check box for associate file group.
	 * Different ScenarioCollection creation method is initiated based on the
	 * user choice.
	 * 
	 * @return Boolean - whether check box is checked
	 */
	public void setAreAssociateFilesRequested(boolean f) {
		arrayAreFilesRequested[0] = f;
	}

	/**
	 * a method to get the array of Strings containing a stack of associate file
	 * paths.
	 * 
	 * @return String[] containing a set of String; return null if no associate
	 *         files are added.
	 */
	public String[] getAssociateFileArray() {
		return arrayStrAssociatedFiles;
	}

	/**
	 * a method to get the list of trajectory files, each of which is to be
	 * associated with a Scenario within this scenario collection
	 * 
	 * @return String[] containing a set of String; return null if no trajectory
	 *         files have been specified by the user.
	 */
	public String[] getArrayStrTrajectoryFilesForReconstructingScenarios() {
		return arrayStrTrajectoryFilesForReconstructingScenarios;
	}

	public ModelVersionID getParentModelVersionID() {
		return modelVersionId;
	}
}
